package com.wjr.braveheart.http.okhttp;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;

import com.wjr.braveheart.dao.IOHandlerFactory;
import com.wjr.braveheart.http.IHttpEngine;
import com.wjr.braveheart.http.ParamsUtils;
import com.wjr.braveheart.http.callback.EngineCallback;
import com.wjr.braveheart.http.callback.EngineDownloadCallback;
import com.wjr.braveheart.http.callback.EngineUploadCallback;
import com.wjr.braveheart.http.okhttp.requestbody.ProgressRequestBody;
import com.wjr.braveheart.http.okhttp.requestbody.ProgressRequestListener;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Email 240336124@qq.com
 * Created by Darren on 2017/3/4.
 * Version 1.0
 * Description: OkHttp默认的引擎
 */
public class OkHttpEngine implements IHttpEngine {

    private static OkHttpClient sOkHttpClient = OkHttpClientUtils.getOkHttpClient();
    private static Handler sHandler = new Handler(Looper.getMainLooper());

    /**
     * Get请求
     *
     * @param cache    是否缓存
     * @param context  上下文
     * @param url      接口
     * @param params   参数
     * @param callback 回调
     */
    @Override
    public void get(final boolean cache, Context context, String url, Map<String, Object> params, final EngineCallback callback) {
        // 请求路径  参数 + 路径代表唯一标识
        HttpUrl.Builder httpUrlBuilder = HttpUrl.parse(url).newBuilder();

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            httpUrlBuilder.addQueryParameter(entry.getKey(), entry.getValue() + "");
        }

        HttpUrl httpUrl = httpUrlBuilder.build();

        final String finalUrl = httpUrl.toString();

        Log.v("Get请求路径：", finalUrl);

        if (cache) {
            final String cacheJson = IOHandlerFactory.getCacheIOHandler().getString(finalUrl);
            if (!TextUtils.isEmpty(cacheJson)) {
                sHandler.post(new Runnable() {
                                  @Override
                                  public void run() {
                                      callback.onSuccess(cacheJson);
                                  }
                              }
                );
            }
        }


        Request.Builder requestBuilder = new Request.Builder().url(httpUrl).tag(context);
        //可以省略，默认是GET请求
        Request request = requestBuilder.build();

        sOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onError(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String resultJson = response.body().string();
                Log.v("响应", resultJson);

                if (cache) {
                    final String cacheJson = IOHandlerFactory.getCacheIOHandler().getString(finalUrl);
                    if (resultJson.equals(cacheJson)) {
                        return;
                    }
                }

                sHandler.post(new Runnable() {
                                  @Override
                                  public void run() {
                                      callback.onSuccess(resultJson);
                                  }
                              }
                );

                IOHandlerFactory.getCacheIOHandler().save(finalUrl, resultJson);
            }
        });
    }

    /**
     * Post请求
     *
     * @param cache    是否缓存
     * @param context  上下文
     * @param url      接口
     * @param params   参数
     * @param callback 回调
     */
    @Override
    public void post(final boolean cache, Context context, String url, Map<String, Object> params, final EngineCallback callback) {

        // 请求路径  参数 + 路径代表唯一标识
        HttpUrl.Builder httpUrlBuilder = HttpUrl.parse(url).newBuilder();

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            httpUrlBuilder.addQueryParameter(entry.getKey(), entry.getValue() + "");
        }

        HttpUrl httpUrl = httpUrlBuilder.build();

        final String finalUrl = httpUrl.toString();
        Log.v("Post请求路径：", finalUrl);

        if (cache) {
            final String cacheJson = IOHandlerFactory.getCacheIOHandler().getString(finalUrl);
            if (!TextUtils.isEmpty(cacheJson)) {
                sHandler.post(new Runnable() {
                                  @Override
                                  public void run() {
                                      callback.onSuccess(cacheJson);
                                  }
                              }
                );
            }
        }

        RequestBody requestBody = ParamsUtils.appendBody(params);
        Request request = new Request.Builder()
                .url(url)
                .tag(context)
                .post(requestBody)
                .build();

        sOkHttpClient.newCall(request).enqueue(
                new Callback() {

                    @Override
                    public void onFailure(Call call, final IOException e) {
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.onError(e);
                            }
                        });
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        final String resultJson = response.body().string();
                        Log.v("Post Response", resultJson);
                        if (cache) {
                            final String cacheJson = IOHandlerFactory.getCacheIOHandler().getString(finalUrl);
                            if (resultJson.equals(cacheJson)) {
                                return;
                            }
                        }

                        sHandler.post(new Runnable() {
                                          @Override
                                          public void run() {
                                              callback.onSuccess(resultJson);
                                          }
                                      }
                        );

                        IOHandlerFactory.getCacheIOHandler().save(finalUrl, resultJson);
                    }
                }
        );
    }

    /**
     * 上传
     *
     * @param context  上下文
     * @param url      接口
     * @param params   参数
     * @param callback 回调
     */
    @Override
    public void upload(Context context, String url, Map<String, Object> params, final EngineUploadCallback callback) {
        final String jointUrl = ParamsUtils.appendParams(url, params);
        Log.v("上传路径：", jointUrl);

        RequestBody requestBody = ParamsUtils.appendBody(params);

        // 扩展一个上传的进度条
        Request request = new Request.Builder()
                .url(url)
                .tag(context)
                .post(new ProgressRequestBody(requestBody, new ProgressRequestListener() {
                    @Override
                    public void onRequestProgress(final long bytesWritten, final long contentLength) {
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.onResponse(bytesWritten, contentLength);
                                if (bytesWritten / contentLength == 1) {
                                    callback.onComplete();
                                }
                            }
                        });
                    }
                })).build();


        sOkHttpClient.newCall(request).enqueue(
                new Callback() {
                    @Override
                    public void onFailure(Call call, final IOException e) {
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.onError(e);
                            }
                        });
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        final String resultJson = response.body().string();
                        Log.v("json->", resultJson);
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.onSuccess(resultJson);
                            }
                        });
                    }
                }
        );
    }

    /**
     * 下载
     *
     * @param url      接口
     * @param callback 回调
     */
    @Override
    public void download(String url, final EngineDownloadCallback callback) {
        Log.v("下载路径：", url);
        Request request = new Request.Builder().url(url).build();

        sOkHttpClient.newCall(request).enqueue(
                new Callback() {
                    @Override
                    public void onFailure(Call call, final IOException e) {
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.onError(e);
                            }
                        });
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        final InputStream is = response.body().byteStream();
                        final long total = response.body().contentLength();
                        callback.onResponse(is, total);
                    }
                }
        );
    }

    /**
     * 取消网络请求
     *
     * @param tag 标记
     */
    @Override
    public void cancel(Context tag) {
        Dispatcher dispatcher = sOkHttpClient.dispatcher();
        synchronized (dispatcher) {
            for (Call call : dispatcher.queuedCalls()) {
                if (tag.equals(call.request().tag())) {
                    call.cancel();
                }
            }
            for (Call call : dispatcher.runningCalls()) {
                if (tag.equals(call.request().tag())) {
                    call.cancel();
                }

            }
        }
    }

}
